import requests, re, json
from urllib.parse import quote, urljoin
from lxml import etree

BASE = "https://www.yinhuadm.xyz"

UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
      "AppleWebKit/537.36 (KHTML, like Gecko) "
      "Chrome/120.0.0.0 Safari/537.36")

sess = requests.Session()
sess.headers.update({
    "user-agent": UA,
    "referer": BASE + "/",
    "accept-language": "zh-CN,zh;q=0.9",
})

def search_anime(name: str):
    url = f"{BASE}/vch/{quote(name)}.html"
    html = sess.get(url, timeout=10).text
    doc = etree.HTML(html)
    # 列表卡片下的详情链接（标题图或标题a）
    links = doc.xpath('//div[contains(@class,"module-card-item")]//a[@href]/@href')
    # 绝对化
    links = [urljoin(BASE, h) for h in links]
    # 去重&只保留到“详情页”/“播放页”的有效链接
    links = [u for u in dict.fromkeys(links) if "/v/" in u or "/p/" in u]
    return links

def pick_first_play_page(detail_or_play_url: str):
    """给一个详情页或播放页，返回某一集的 /p/{id}-line-ep.html 播放页 URL"""
    html = sess.get(detail_or_play_url, timeout=10).text
    doc  = etree.HTML(html)
    # 已经是播放页：/p/4870-1-1.html
    if "/p/" in detail_or_play_url:
        return detail_or_play_url

    # 详情页一般会给“选集”的 a 链接（指向 /p/...）
    play_urls = doc.xpath('//a[contains(@href,"/p/")]/@href')
    play_urls = [urljoin(BASE, u) for u in play_urls]
    play_urls = [u for u in play_urls if "/p/" in u]
    return play_urls[0] if play_urls else None

PLAYER_RE = re.compile(r'var\s+player_[a-zA-Z0-9_]+\s*=\s*(\{.*?\});', re.S)

def extract_player_config(play_page_url: str):
    """从播放页拿到播放器参数（JSON），或者 iframe src"""
    html = sess.get(play_page_url, timeout=10).text

    # 方案A：苹果CMS系常见：<script>var player_aaaa = {...}</script>
    m = PLAYER_RE.search(html)
    if m:
        raw = m.group(1)
        # 防御性 JSON 解析：去掉尾逗号等
        raw = raw.replace(",}", "}").replace(",]", "]")
        cfg = json.loads(raw)
        return {"type": "json", "data": cfg}

    # 方案B：直接有 iframe
    doc = etree.HTML(html)
    iframe = doc.xpath('//iframe[@src]/@src')
    if iframe:
        return {"type": "iframe", "data": urljoin(play_page_url, iframe[0])}

    # 兜底：有些把 url 写在 data-xxx 属性里
    data_url = doc.xpath('//*[starts-with(@data-,"http")]/@data-url')
    if data_url:
        return {"type": "iframe", "data": urljoin(play_page_url, data_url[0])}

    raise RuntimeError("在播放页里没找到 player 配置或 iframe，可能页面换版或需要JS执行。")

def resolve_real_media(player_info: dict):
    """把 player 配置/iframe 再往下走，尽量还原出 mp4/m3u8（不保证每次都能直连成功）"""
    if player_info["type"] == "json":
        cfg = player_info["data"]
        # 常见字段：from, url, id, next, title ...
        # 有些站把真正的第三方播放器页面放在 cfg['url'] 或拼在一个 player 路径模板上
        third = cfg.get("url") or cfg.get("link") or ""
        if third.startswith("//"):
            third = "https:" + third
        if third and third.startswith("http"):
            r = sess.get(third, timeout=10).text
            # 很多第三方播放器会在它的页面里再放一段含有 m3u8/mp4 的 JSON
            # 简陋地扒一扒：
            m3u8s = re.findall(r'https?://[^\s"\']+\.m3u8[^\s"\']*', r)
            mp4s  = re.findall(r'https?://[^\s"\']+\.mp4[^\s"\']*', r)
            if m3u8s or mp4s:
                return {"m3u8": m3u8s, "mp4": mp4s, "via": third}
            # 也可能又嵌一层 iframe：
            m_if = re.search(r'<iframe[^>]+src=["\']([^"\']+)["\']', r, re.I)
            if m_if:
                iframe2 = urljoin(third, m_if.group(1))
                r2 = sess.get(iframe2, timeout=10).text
                m3u8s2 = re.findall(r'https?://[^\s"\']+\.m3u8[^\s"\']*', r2)
                mp4s2  = re.findall(r'https?://[^\s"\']+\.mp4[^\s"\']*', r2)
                if m3u8s2 or mp4s2:
                    return {"m3u8": m3u8s2, "mp4": mp4s2, "via": iframe2}
        return {"hint": "拿到了 player JSON，但没直接扒到直链", "player": cfg}

    else:  # iframe
        iframe = player_info["data"]
        html = sess.get(iframe, timeout=10).text
        m3u8s = re.findall(r'https?://[^\s"\']+\.m3u8[^\s"\']*', html)
        mp4s  = re.findall(r'https?://[^\s"\']+\.mp4[^\s"\']*', html)
        if m3u8s or mp4s:
            return {"m3u8": m3u8s, "mp4": mp4s, "via": iframe}
        # 再试一层 iframe
        m_if = re.search(r'<iframe[^>]+src=["\']([^"\']+)["\']', html, re.I)
        if m_if:
            iframe2 = urljoin(iframe, m_if.group(1))
            html2 = sess.get(iframe2, timeout=10).text
            m3u8s2 = re.findall(r'https?://[^\s"\']+\.m3u8[^\s"\']*', html2)
            mp4s2  = re.findall(r'https?://[^\s"\']+\.mp4[^\s"\']*', html2)
            if m3u8s2 or mp4s2:
                return {"m3u8": m3u8s2, "mp4": mp4s2, "via": iframe2}
        return {"hint": "iframe里没直接出现直链，可能需要执行JS或带cookie。", "iframe": iframe}

if __name__ == "__main__":
    name = "斗破苍穹"
    detail_links = search_anime(name)
    print("详情/播放候选：", detail_links[:5])

    play = pick_first_play_page(detail_links[0])
    print("播放页：", play)

    info = extract_player_config(play)
    print("player info:", info["type"])

    real = resolve_real_media(info)
    print(real)